package com.mini.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Splitter;
import com.mini.conditon.BusinessConditionNew;
import com.mini.constant.RedisKeyConst;
import com.mini.model.BusinessBaseInfo;
import com.mini.repository.BusinessBaseInfoRepository;
import com.mini.req.BusinessBaseInfoNew;
import com.mini.util.MatcherRule;
import com.mini.vo.BusinessResult;
import com.mini.vo.CommonResultMessage;
import com.mini.vo.PageResultVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author zhangxiaobin
 * @title: MiniLessonBaseInfoService
 * @description: TODO
 * @date 2019/10/2711:34
 */
@Service
@Slf4j
public class BusinessBaseService extends BaseService {

    @Autowired
    private BusinessBaseInfoRepository businessBaseInfoRepository;


    public void save(BusinessBaseInfo businessBaseInfo){
        businessBaseInfoRepository.save(businessBaseInfo);
        removeCacheKey(businessBaseInfo.getMiniLessonId());
    }

    public BusinessResult<BusinessBaseInfo> getBusinessBaseInfoBusinessResult(List<BusinessBaseInfoNew> businessBaseInfoNewLists, List<String> errorMsgs, Long userId) {
        String baseKey = RedisKeyConst.getBusinessNewFlag( "base", userId);
        redisTemplate.delete(baseKey);
        int len = businessBaseInfoNewLists.size();
        for (int i = len-1; i >= 0; i--) {
            BusinessBaseInfoNew businessBaseInfoNew = businessBaseInfoNewLists.get(i);
            Integer siteType = businessBaseInfoNew.getSiteType();
            if(siteType == null || siteType == 0){//分配平台 飞天系统 =0，星图天网=1
                checkParamForFlySky(businessBaseInfoNew,errorMsgs);
            }else if(siteType == 1) {//传统
                checkParamForNormal(businessBaseInfoNew,errorMsgs);
            }
            //校验星图站点是否符合规则
            if(StringUtils.isNotBlank(businessBaseInfoNew.getXingtuSite())){

                checkXingTuSite(businessBaseInfoNew.getSiteType(),businessBaseInfoNew.getXingtuSite());
            }

            String reqParms = JSON.toJSONString(businessBaseInfoNew);
            if(errorMsgs.size() > 0){
                log.error("申请小课站点ID params error, req=【{}】, res = {}", reqParms, JSON.toJSONString(errorMsgs));
                return BusinessResult.createInstance(CommonResultMessage.PARAMS_ERROR, businessBaseInfoNew.getMiniLessonName()+"_"+ JSONObject.toJSONString(errorMsgs));
            }

            try{
                BusinessBaseInfo businessBaseInfo = add(businessBaseInfoNew);
                redisTemplate.opsForSet().add(baseKey, businessBaseInfo.getMiniLessonId());
                log.debug("创建小课站点 req={}, response={}", businessBaseInfoNew, businessBaseInfo);
            }catch (Exception ex){
                sendEmail("申请小课站点ID system error,req=【"+ reqParms +"】ex=【"+ex.getMessage()+"】");
                log.error("申请小课站点ID system error , req=【{}】, ex= {} ", reqParms, ex);
            }
        }
        redisTemplate.expire(baseKey, 30, TimeUnit.DAYS);
        return null;
    }

    public void checkParamForFlySky(BusinessBaseInfoNew businessBaseInfoNew,List<String> errorMsgs) {
        if(businessBaseInfoNew.getSiteType()== null) {
            errorMsgs.add("站点类型 飞天系统 =0，传统=1 为空");
        }
        if (StringUtils.isBlank(businessBaseInfoNew.getMiniLessonName())) {
            errorMsgs.add("小课名称为空");
        }
        String groupIds = businessBaseInfoNew.getArmyGroupId();
        if (StringUtils.isBlank(groupIds) || ",".equalsIgnoreCase(groupIds)) {
            errorMsgs.add("军团id值不能为空");
        }
        String groupNames = businessBaseInfoNew.getArmyGroupName();
        if (StringUtils.isBlank(groupNames) || ",".equalsIgnoreCase(groupNames)) {
            errorMsgs.add("军团Names值不能为空");
        }
        if (businessBaseInfoNew.getChannelId() == null || businessBaseInfoNew.getChannelId().intValue() == 0) {
            errorMsgs.add("channelId值不能为空");
        }
        if (businessBaseInfoNew.getCreateUserId() == null || businessBaseInfoNew.getCreateUserId().intValue() == 0) {
            errorMsgs.add("userid 值不能为空");
        }

        if (StringUtils.isBlank(businessBaseInfoNew.getQuantumGroupId())) {
            errorMsgs.add("量子军团id 不能为空");
        }
        if (StringUtils.isBlank(businessBaseInfoNew.getQuantumGroupName())) {
            errorMsgs.add("量子军团名称 不能为空");
        }
        if (businessBaseInfoNew.getFzId() == null || businessBaseInfoNew.getFzId() == 0) {
            errorMsgs.add("负责人id 不能为空");
        }
        if (StringUtils.isBlank(businessBaseInfoNew.getFzName())) {
            errorMsgs.add("负责人名称 不能为空");
        }

        if (businessBaseInfoNew.getSiteModel() == null) {
            errorMsgs.add("AB模式 不能为空");
            businessBaseInfoNew.setSiteModel(businessBaseInfoNew.getSiteModel());
        }

//        if( StringUtils.isBlank(businessBaseInfoNew.getXingtuSite())){
//            errorMsgs.add("星图站点 不能为空");
//        }else{
            if(StringUtils.isNotBlank(businessBaseInfoNew.getXingtuSite())){

                Integer xingtuSiteModel = checkXingTuSite(businessBaseInfoNew.getXingtuSite());
                if(xingtuSiteModel == null){
                    errorMsgs.add("星图站点="+businessBaseInfoNew.getXingtuSite()+",不合法");
                    throw new RuntimeException("xingtuSite_"+businessBaseInfoNew.getXingtuSite()+"_不合法");
                }else{
                    if(xingtuSiteModel != 2){//xyf add 强制要求必须填B模式站点
                        errorMsgs.add("星图站点="+businessBaseInfoNew.getXingtuSite()+",请填写B模式站点");
                        throw new RuntimeException("xingtuSite_"+businessBaseInfoNew.getXingtuSite()+"_请填写B模式站点");
                    }
//                    businessBaseInfoNew.setSiteModel(xingtuSiteModel);
                }
            }
//        }

    }
    public void checkParamForNormal(BusinessBaseInfoNew businessBaseInfoNew,List<String> errorMsgs){
        if(businessBaseInfoNew.getSiteType()== null) {
            errorMsgs.add("站点类型 飞天系统 =0，传统=1 为空");
        }
        if(StringUtils.isBlank(businessBaseInfoNew.getMiniLessonName())) {
            errorMsgs.add("小课名称为空");
        }

        if(businessBaseInfoNew.getChannelId() == null || businessBaseInfoNew.getChannelId().intValue() == 0){
            errorMsgs.add("channelId值不能为空");
        }
        if(businessBaseInfoNew.getCreateUserId() == null || businessBaseInfoNew.getCreateUserId().intValue() == 0){
            errorMsgs.add("userid 值不能为空");
        }

        if(businessBaseInfoNew.getSiteItem() == null || businessBaseInfoNew.getSiteItem().intValue() == 0){
            errorMsgs.add("项目值不能为空");
        }



        if(businessBaseInfoNew.getFzId() == null || businessBaseInfoNew.getFzId() == 0){
            errorMsgs.add("负责人id 不能为空");
        }
        if(StringUtils.isBlank(businessBaseInfoNew.getFzName())){
            errorMsgs.add("负责人名称 不能为空");
        }
        if( StringUtils.isBlank(businessBaseInfoNew.getXingtuSite())){
            errorMsgs.add("星图站点 不能为空");
        }else{
            if(StringUtils.isNotBlank(businessBaseInfoNew.getXingtuSite())){

                Integer xingtuSiteModel = checkXingTuSite(businessBaseInfoNew.getXingtuSite());
                if(xingtuSiteModel == null){
                    errorMsgs.add("星图站点="+businessBaseInfoNew.getXingtuSite()+",不合法");
                    throw new RuntimeException("xingtuSite_"+businessBaseInfoNew.getXingtuSite()+"_不合法");
                }else{
                    businessBaseInfoNew.setSiteModel(xingtuSiteModel);
                }
            }
        }

    }

    public void checkXingTuSite(Integer siteType,String xingTuSite ){
        List<BusinessBaseInfo> list = businessBaseInfoRepository.findBySiteTypeAndXingtuSite(siteType, xingTuSite);
        if(siteType == 0){//如果是飞天分配 全站点不能有重复的星图站点
            if(list != null && !list.isEmpty()){
                throw new RuntimeException("xingtuSite_"+xingTuSite+"_该星图站点已绑定飞天站点"+list.get(0).getMiniLessonId()+"，星图站点只能绑定一个飞天站点");
            }
        }else  if(siteType == 1){//如果是星图分配，1、飞天类的站点如果用了，则不能再使用 2、飞天类的站点如果没用，星图站点用了，可以重复使用
            if(list != null && !list.isEmpty()){
                for(BusinessBaseInfo businessBaseInfo : list){
                    if(businessBaseInfo.getSiteType() == 0 && (businessBaseInfo.getXingtuSite() != null && xingTuSite.equals(businessBaseInfo.getXingtuSite()))){
                        throw new RuntimeException("xingtuSite_"+xingTuSite+"_该星图站点已绑定飞天站点"+businessBaseInfo.getMiniLessonId()+"，星图站点只能绑定一个飞天站点");
                    }
                }
            }

        }


    }




    public BusinessBaseInfo add(BusinessBaseInfoNew businessBaseInfoNew){
        BusinessBaseInfo newBusinessBaseInfo;
        BusinessBaseInfo businessBaseInfo = new BusinessBaseInfo();
        BeanUtil.copyProperties(businessBaseInfoNew, businessBaseInfo,true, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        businessBaseInfo.setCreateTime(new Date());
        businessBaseInfo.setUpdateTime(new Date());
        newBusinessBaseInfo = businessBaseInfoRepository.save(businessBaseInfo);
        removeCacheKey(newBusinessBaseInfo.getMiniLessonId());
        return newBusinessBaseInfo;
    }




    public BusinessBaseInfo getByMiniLessonId(Long miniLessonId){
        String businessInfoKey = RedisKeyConst.getBusinessInfo(miniLessonId);
        Object o = redisTemplate.opsForValue().get(businessInfoKey);
        if(o == null) {
            BusinessBaseInfo one = businessBaseInfoRepository.findOne(miniLessonId);
            if(one != null){
                redisTemplate.opsForValue().set(businessInfoKey,one,30, TimeUnit.DAYS);
            }
            return one;
        }
        return (BusinessBaseInfo)o;
    }
    public List<BusinessBaseInfo> getBaseInfoList(Set<Long> ids){
        return businessBaseInfoRepository.findAllByMiniLessonIdIn(ids);
    }

    public BusinessBaseInfo getByMiniLessonIdNoCache(Long miniLessonId){
        BusinessBaseInfo one = businessBaseInfoRepository.findOne(miniLessonId);
        return one;
    }


    private void removeCacheKey(Long businessId){
        String businessInfoKey = RedisKeyConst.getBusinessInfo(businessId);
        redisTemplate.delete(businessInfoKey);
    }



    public PageResultVO<BusinessBaseInfo> pageNew(BusinessConditionNew condition){
        PageResultVO<BusinessBaseInfo> resultVO = new PageResultVO<>();
        List<String> orderKeys = new ArrayList<>();
        if(StringUtils.isNotEmpty(condition.getSortColumn())){
            orderKeys.add(condition.getSortColumn());
            orderKeys.add("miniLessonId");
        }
        Pageable pageable = null;
        Sort sort = null;
        if(StringUtils.isNotEmpty(condition.getSortType()) && StringUtils.isNotEmpty(condition.getSortColumn())){
            sort = new Sort(Sort.Direction.valueOf(condition.getSortType()),orderKeys);
        }
        pageable = buildPageRequest(condition.getPageNumber(),condition.getPageSize(),sort);
        Page<BusinessBaseInfo> page = businessBaseInfoRepository.findAll(new Specification<BusinessBaseInfo>() {
            @Override
            public Predicate toPredicate(Root<BusinessBaseInfo> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();

                //传统增加
                if(condition.getSiteType() == null || condition.getSiteType() == 0){
                    predicates.add(criteriaBuilder.equal(root.get("siteType").as(Integer.class), 0));
                }else {
                    predicates.add(criteriaBuilder.equal(root.get("siteType").as(Integer.class), condition.getSiteType()));
                }


                if(StringUtils.isNotBlank(condition.getXingtuSite() ) ){
                    predicates.add(criteriaBuilder.like(root.get("xingtuSite").as(String.class), "%"+condition.getXingtuSite()+"%"));
                }

                if(condition.getSiteModel() != null ){
                    predicates.add(criteriaBuilder.equal(root.get("siteModel").as(String.class), condition.getSiteModel()));
                }

                if(StringUtils.isNotBlank(condition.getSiteItem()) && StringUtils.isNotBlank(condition.getSiteItem().trim() )  ){
                    predicates.add(criteriaBuilder.equal(root.get("siteItem").as(Integer.class), Integer.parseInt(condition.getSiteItem())));
                }
                //传统增加end

                if(StringUtils.isNotBlank(condition.getMiniLesson())){
                    if (MatcherRule.isInteger(condition.getMiniLesson()) && 0 != Long.parseLong(condition.getMiniLesson())) {
//                        predicates.add(criteriaBuilder.equal(root.get("miniLessonId").as(Long.class), condition.getMiniLesson()));
                        predicates.add(criteriaBuilder.or(criteriaBuilder.like(root.get("miniLessonId").as(String.class), "%"+condition.getMiniLesson()+"%"),
                                criteriaBuilder.like(root.get("miniLessonName").as(String.class), "%"+condition.getMiniLesson()+"%")));
                    } else {
                        predicates.add(criteriaBuilder.like(root.get("miniLessonName").as(String.class), "%"+condition.getMiniLesson()+"%"));
                    }
                }
                if(condition.getFzId() != null && 0 != condition.getFzId().longValue()){
                    predicates.add(criteriaBuilder.equal(root.get("fzId").as(Long.class), condition.getFzId()));
                }else{
                    if(condition.getCreateUserId() != null && 0 != condition.getCreateUserId().intValue()){
                        List<Long> userids = scopedAdvertisingUserIds(condition.getCreateUserId());
                        CriteriaBuilder.In<Long> in = criteriaBuilder.in(root.get("fzId"));
                        Iterator<Long> it = userids.iterator();
                        while (it.hasNext()){
                            in.value(it.next());
                        }
                        predicates.add(in);
                    }
                }


                if(StringUtils.isNotBlank(condition.getArmyGroupId())){
                    List<String> groupIdList = new ArrayList<>(Splitter.on(",").splitToList(condition.getArmyGroupId()));
                    Collections.sort(groupIdList);
                    predicates.add(criteriaBuilder.equal(root.get("armyGroupId").as(String.class), String.join(",", groupIdList)));
                }

                if(StringUtils.isNotBlank(condition.getQuantumGroupId())){
                    List<String> groupIdList = new ArrayList<>(Splitter.on(",").splitToList(condition.getQuantumGroupId()));
                    Collections.sort(groupIdList);
                    predicates.add(criteriaBuilder.equal(root.get("quantumGroupId").as(String.class), String.join(",", groupIdList)));
                }
                if (null != condition.getChannelId()) {
                    predicates.add(criteriaBuilder.equal(root.get("channelId").as(String.class), condition.getChannelId()));
                }
                if (StringUtils.isNotEmpty(condition.getRegion())) {
                    List<String> region = new ArrayList<>(Splitter.on(",").splitToList(condition.getRegion()));
                    for(String recode : region){
                        predicates.add(criteriaBuilder.like(root.get("regionCode").as(String.class), "%"+recode+"%"));
                    }

                }



                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        }, pageable);
        resultVO.setTotal(page.getTotalElements());
        resultVO.setRows(page.getContent());
        return resultVO;
    }


    /**
     * 根据 投放渠道 负责人 查询站点列表
     * @param condition
     * @return
     */
    public List<BusinessBaseInfo> getAllByCondition(BusinessConditionNew condition){
        List<BusinessBaseInfo> page = businessBaseInfoRepository.findAll(new Specification<BusinessBaseInfo>() {
            @Override
            public Predicate toPredicate(Root<BusinessBaseInfo> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();


                //传统增加end

                if(condition.getFzId() != null && 0 != condition.getFzId().longValue()){
                    predicates.add(criteriaBuilder.equal(root.get("fzId").as(Long.class), condition.getFzId()));
                }


                if (null != condition.getChannelId()) {
                    predicates.add(criteriaBuilder.equal(root.get("channelId").as(String.class), condition.getChannelId()));
                }

                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        });
        return page;
    }




    /**
     * 设置小课业务/传统机会 开关选择
     * @param siteType
     * @param loginUserId
     */
    public void setZHLastState(Integer siteType,Long loginUserId){
        String businessInfoKey = RedisKeyConst.getZHLastState(loginUserId);
        redisTemplate.opsForValue().set(businessInfoKey,siteType);
    }

    /**
     * 查询小课业务/传统机会 开关选择
     * @param loginUserId
     * @return
     */
    public Integer getZHLastState(Long loginUserId){
        String businessInfoKey = RedisKeyConst.getZHLastState(loginUserId);
        Object o = redisTemplate.opsForValue().get(businessInfoKey);
        if(o != null){
            return (Integer) o;
        }else{
            return 0;
        }
    }

    public  List<BusinessBaseInfo> getBusinessBaseInfoBySiteModel(Integer siteModel){
        return  businessBaseInfoRepository.findBySiteType(siteModel);

    }

    /**
     * 查询当前负责人当日的站点列表
     * @param condition
     * @return
     */
    public List<BusinessBaseInfo> nowNewSiteList(BusinessConditionNew condition){
        List<BusinessBaseInfo> page =businessBaseInfoRepository.findAll(
                new Specification<BusinessBaseInfo>() {
                    @Override
                    public Predicate toPredicate(Root<BusinessBaseInfo> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                        List<Predicate> predicates = new ArrayList<>();


                        if(condition.getCreateUserId() != null && 0 != condition.getCreateUserId().intValue()){
                            List<Long> userids = scopedAdvertisingUserIds(condition.getCreateUserId());
                            CriteriaBuilder.In<Long> in = criteriaBuilder.in(root.get("fzId"));
                            Iterator<Long> it = userids.iterator();
                            while (it.hasNext()){
                                in.value(it.next());
                            }
                            predicates.add(in);
                        }

                        if( StringUtils.isNotBlank(condition.getBeginTime()) ){
                            String beginTime = condition.getBeginTime();
                            predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime").as(String.class) , beginTime + " 00:00:00"));
                        }

                        return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
                    }
                }

        );
        return page;
    }

}

